home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / ISSUE21 / TIPTRIX / LISTING4.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1997-04-16  |  5.9 KB  |  198 lines

  1. procedure SetHeadings;
  2. var
  3.    slstHotKeys, slstHotKeysSave: TStringList;
  4.  
  5.    procedure SetTab(pageIndex: integer; header: string);
  6.    begin
  7.       { hot keys that can't be used are <slstHotKeysSave> = main menu,
  8.         notebook tabs, toolbar, popup
  9.         this list must be added to for each each successive page }
  10.       slstHotKeys.Assign(slstHotKeysSave);
  11.       GetHotkeysInWinControl(TTabPages(nbk.Pages.Objects[pageIndex]),
  12.                              slstHotKeys, nil);
  13.       SetAcceleratorKey(slstHotKeys, header);
  14.       nbk.TabCaption[pageIndex] := header;
  15.       slstHotKeys.Clear;
  16.    end;
  17. begin
  18.    slstHotKeys := TStringList.Create;
  19.    slstHotKeysSave := TStringList.Create;
  20.    try
  21.       { pass nil as confident that form does not contain duplicates }
  22.       GetHotKeysInMainMenu(form1.mnuMain, slstHotkeysSave, nil);
  23.       GetHotKeysInNbkTabs(nbk, slstHotKeysSave, nil);
  24.       GetHotKeysInShortCuts(pop, slstHotKeysSave, nil);
  25.  
  26.       { tab names could be obtained at run-time from some misc source }
  27.       SetHeading(1, 'First');
  28.       SetHeading(2, 'Second');
  29.       SetHeading(3, 'Third');
  30.       SetHeading(4, 'Fourth');
  31.       SetHeading(5, 'Fifth');
  32.    finally
  33.       slstHotKeys.Free;
  34.       slstHotKeysSave.Free;
  35.    end;
  36. end;
  37.  
  38. procedure GetHotKeysInWinControl(ctrl: TWinControl; slstHotkeys,
  39. slstDuplicates: TStringList);
  40.    procedure ChkValidAndAdd(ctrl: TControl);
  41.    var
  42.       hotKey: string;
  43.    begin
  44.       if HasNamedProperty(ctrl, 'Caption') then begin
  45.          { can use anything to typecast as long as it has a caption property }
  46.          hotKey := GetHotKey(TLabel(ctrl).Caption, False);
  47.          AddHotKey(slstHotkeys, slstDuplicates, hotKey);
  48.       end;
  49.    end;
  50.  
  51.    procedure CycleControls(ctrl: TWinControl);
  52.    var
  53.       i: integer;
  54.    begin
  55.       { use recursion to check for hotkeys on nested TWinControls }
  56.       if ctrl.ControlCount > 0 then
  57.          for i := 0 to ctrl.ControlCount - 1 do begin
  58.             if ctrl.Controls[i] is TWinControl then
  59.                CycleControls(TWinControl(ctrl.Controls[i]));
  60.             ChkValidAndAdd(ctrl.Controls[i]);
  61.          end;
  62.    end;
  63. begin
  64.    CycleControls(ctrl);
  65. end;
  66.  
  67. procedure AddHotKey(slstHotkeys, slstDuplicates: TStringList; hotKey: string);
  68. begin
  69.    if hotkey <> '' then
  70.      { returns -1 if check not in lst, otherwise returns index }
  71.      if slstHotKeys.IndexOf(hotKey) = -1 then
  72.         slstHotKeys.Add(hotkey)
  73.      else
  74.         if Assigned(slstDuplicates) then
  75.            slstDuplicates.Add(hotKey);
  76. end;
  77.  
  78. procedure SetAcceleratorKey(slstHotKeys: TStringList; var toSet: string);
  79. var
  80.    j: integer;
  81.    inList, found : boolean;
  82.    ch : string;
  83. begin
  84.    j := 1;
  85.    found := false;
  86.    while not found do begin
  87.       ch := UpperCase( toSet[j] );
  88.       inList := (slstHotKeys.IndexOf(ch) <> -1);
  89.  
  90.       if (not inList) and (ch <> #32) then begin
  91.          slstHotKeys.Add(ch);
  92.          toSet := Copy( toSet, 1, j-1 ) + '&' + Copy( toSet, j, Length(toSet) );
  93.          found := true;
  94.       end else begin
  95.          inc(j);
  96.          found := (j > Length(toSet));
  97.       end
  98.    end;
  99. end;
  100.  
  101. function HasNamedProperty(AComponent: TComponent; const propertyName: string): boolean;
  102. var
  103.    propInfo: PPropInfo;
  104. begin
  105.    propInfo := GetPropInfo(AComponent.ClassInfo, propertyName);
  106.    Result := (propInfo <> nil);
  107. end;
  108.  
  109. procedure GetHotKeysInNbkTabs(ctrl: TWinControl; slstHotkeys, slstDuplicates: TStringList);
  110. var
  111.    i: integer;
  112.    str : TStrings;
  113.    hotKey: string;
  114. begin
  115.    { setup for 2 notebooks }
  116.    if ctrl is TTabbedNotebook then
  117.       str := (ctrl as TTabbedNotebook).Pages
  118.    else if ctrl is TcsNotebook then
  119.       { Classic notebook }
  120.       str := (ctrl as TCsNotebook).Pages
  121.    else
  122.       Exit;
  123.  
  124.    { add hotkeys on notebook tabs }
  125.    for i := 0 to str.Count - 1 do begin
  126.       hotKey := GetHotKey(str.Strings[i], False);
  127.       AddHotKey(slstHotkeys, slstDuplicates, hotKey);
  128.    end;
  129. end;
  130.  
  131. procedure GetHotkeysInMainMenu(mnu: TMainMenu; slstHotkeys, slstDuplicates: TStringList);
  132. var
  133.    i: integer;
  134.    hotKey: string;
  135. begin
  136.    for i := 0 to mnu.Items.Count - 1 do begin
  137.       hotKey := GetHotKey(mnu.Items[i].Caption, True);
  138.       AddHotKey(slstHotkeys, slstDuplicates, hotKey);
  139.    end;
  140. end;
  141.  
  142. procedure GetHotKeysInShortCuts(mnu: TMenu; slstHotkeys, slstDuplicates: TStringList);
  143. { use TMenu arguement so can pass TMainMenu and TPopupMenu }
  144.    procedure CycleMenu(itm: TMenuItem);
  145.    var
  146.       i: integer;
  147.       hotKey: string;
  148.       function GetHotKeyInShortCut(strShortCut: string): string;
  149.       { only will conflict with hotkey if shortcut in Alt+? format }
  150.       begin
  151.          Result := '';
  152.          if Copy(strShortCut, 1, 3) = 'Alt' then
  153.             Result := Copy(strShortCut, 5, 1);
  154.       end;
  155.    begin
  156.       { use recursion to check for hotkeys in nested TMenuItems }
  157.       if itm.Count > 0 then
  158.          for i := 0 to itm.Count - 1 do begin
  159.             CycleMenu(itm.Items[i]);
  160.             if itm[i].ShortCut <> 0 then begin
  161.                hotKey := GetHotKeyInShortCut(ShortCutToText(itm[i].ShortCut));
  162.                AddHotKey(slstHotkeys, slstDuplicates, hotKey);
  163.             end;
  164.          end;
  165.    end;
  166. begin
  167.    CycleMenu(mnu.Items);
  168. end;
  169.  
  170. function GetHotKey(str: string; msg: boolean): string;
  171. var
  172.    i: integer;
  173.    length: byte absolute str;
  174.    nextChar: string;
  175. begin
  176.    i := 1;
  177.    nextChar := Copy(str, i, 1);
  178.    while ((nextChar <> '&') and (i <= length)) do begin
  179.       Inc(i);
  180.       nextChar := Copy(str, i, 1);
  181.    end;
  182.  
  183.    if (i = length) then begin
  184.       { nextChar could be & or not }
  185.       if msg then
  186.          { self check - should never go in here (for TMenuItems) }
  187.          MsgError(Format('%s has no hotkey', [str]));
  188.       Result := '';
  189.    end else
  190.       Result :=  Copy(str, i + 1, 1);
  191. end;
  192.  
  193. { Tom Corcoran, Unitime Systems
  194.   s-mail:    3101 Iris Avenue, Suite 240, Boulder,
  195.              Colorado 80301-1900, USA
  196.   e-mail:    tomc@unitime.com OR
  197.              tomcorcora@aol.com  }
  198.